package com.zzyl.nursing.service.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.List;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zzyl.common.exception.ServiceException;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.common.utils.uuid.IdUtils;
import com.zzyl.nursing.domain.*;
import com.zzyl.nursing.dto.CheckInApplyDto;
import com.zzyl.nursing.dto.CheckInConfigDto;
import com.zzyl.nursing.dto.CheckInElderDto;
import com.zzyl.nursing.mapper.*;
import com.zzyl.nursing.vo.CheckInConfigVo;
import com.zzyl.nursing.vo.CheckInDetailVo;
import com.zzyl.nursing.vo.CheckInElderVo;
import com.zzyl.nursing.vo.ElderFamilyVo;
import com.zzyl.utils.CodeGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.service.ICheckInService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.stream.Collectors;

/**
 * 入住Service业务层处理
 * 
 * @author laoYe
 * @date 2025-10-21
 */
@Slf4j
@Service
public class CheckInServiceImpl extends ServiceImpl<CheckInMapper, CheckIn> implements ICheckInService {
    @Autowired
    private CheckInMapper checkInMapper;
    @Autowired
    private ElderMapper elderMapper;
    @Autowired
    private BedMapper bedMapper;
    @Autowired
    private CheckInConfigMapper checkInConfigMapper;
    @Autowired
    private ContractMapper contractMapper;

    /**
     * 查询入住
     * 
     * @param id 入住主键
     * @return 入住
     */
    @Override
    public CheckIn selectCheckInById(Long id) {
        return getById(id);
    }

    /**
     * 查询入住列表
     * 
     * @param checkIn 入住
     * @return 入住
     */
    @Override
    public List<CheckIn> selectCheckInList(CheckIn checkIn) {
        return checkInMapper.selectCheckInList(checkIn);
    }

    /**
     * 新增入住
     * 
     * @param checkIn 入住
     * @return 结果
     */
    @Override
    public int insertCheckIn(CheckIn checkIn) {
        return save(checkIn) ? 1 : 0;
    }

    /**
     * 修改入住
     * 
     * @param checkIn 入住
     * @return 结果
     */
    @Override
    public int updateCheckIn(CheckIn checkIn) {
        return updateById(checkIn) ? 1 : 0;
    }

    /**
     * 批量删除入住
     * 
     * @param ids 需要删除的入住主键
     * @return 结果
     */
    @Override
    public int deleteCheckInByIds(Long[] ids) {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除入住信息
     * 
     * @param id 入住主键
     * @return 结果
     */
    @Override
    public int deleteCheckInById(Long id) {
        return removeById(id) ? 1 : 0;
    }

    /**
     * 申请入住
     * @param dto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void apply(CheckInApplyDto dto) {
        log.info("开始处理入住申请");
        //1判断老人是否入住，通过身份证查询老人的信息
        //通过前端传递进来的实体类中获取老人信息
        //创建一个老人信息对象
        CheckInElderDto checkInElderDto = dto.getCheckInElderDto();
        //通过eq(Elder::getIdCardNo,checkInElderDto.getIdCardNo())对比数据库中身份证信息判断是否有前端传进来的老人的信息
        Elder elderInDb = elderMapper.selectOne(new LambdaQueryWrapper<Elder>().eq(Elder::getIdCardNo,checkInElderDto.getIdCardNo()));
        log.info("数据库中老人的信息：{}",elderInDb);
        if (elderInDb != null){
            log.info("数据库中老人已存在");
            //判断状态，0：禁用，1:启用,2:请假,3:退住中,4:入住中,5:已退住，2345中任意一个状态的都为入住中
            if(elderInDb.getStatus()>=2 && elderInDb.getStatus()<=4){
                throw new ServiceException("老人已入住");
            }
        }
        //排除以上情况，则该老人没有入住
        //2.更新床位的状态
        //通过前端传来的checkIn对象获取床位id，即新增老人选择的床位，需修改该床位id的状态
        Long bedId = dto.getCheckInConfigDto().getBedId();
        //修改床位状态，更新床位状态，updateBedStatus方法返回0，则修改失败，1，则修改成功
        int num = bedMapper.updateBedStatus(bedId);
        //判断修改结果
        if (num == 0){
            throw new ServiceException("该床位已经被占用了，请选择其它的床位");
        }
        log.info("修改床位状态成功");
        //新增或更新老人的信息
        Elder elder = addOrUpdateElder(checkInElderDto, bedId, elderInDb);
        //新增入住的信息
        CheckIn checkIn = addCheckIn(dto,elder);
        //新增入住配置信息
        addCheckInConfig(dto, checkIn);
        //新增签约办理信息
        addContract(dto, elder, checkIn);


    }
    /**
     * 获取入住详情
     * @param id
     * @return
     */
    @Override
    public CheckInDetailVo detail(Long id) {
        CheckInDetailVo detailVo = new CheckInDetailVo();

        // 查询入住信息
        CheckIn checkIn = this.getById(id);
        if (checkIn == null) {
            throw new RuntimeException("入住信息不存在");
        }

        // 查询老人信息
        if (checkIn.getElderId() != null) {
            Elder elder = elderMapper.selectElderById(checkIn.getElderId());
            if (elder != null) {
                CheckInElderVo elderVo = new CheckInElderVo();
                elderVo.setId(elder.getId());
                elderVo.setName(elder.getName());
                elderVo.setIdCardNo(elder.getIdCardNo());
                elderVo.setBirthday(elder.getBirthday());
                elderVo.setSex(elder.getSex());
                elderVo.setPhone(elder.getPhone());
                elderVo.setAddress(elder.getAddress());
                elderVo.setImage(elder.getImage());
                elderVo.setIdCardNationalEmblemImg(elder.getIdCardNationalEmblemImg());
                elderVo.setIdCardPortraitImg(elder.getIdCardPortraitImg());

                // 计算年龄（可选）
                if (elder.getBirthday() != null && !elder.getBirthday().isEmpty()) {
                    try {
                        LocalDate birthDate = LocalDate.parse(elder.getBirthday());
                        int age = Period.between(birthDate, LocalDate.now()).getYears();
                        elderVo.setAge(age);
                    } catch (Exception e) {
                    }
                }
                // 添加到详情对象中
                detailVo.setCheckInElderVo(elderVo);
            }
        }
        // 查询家属信息
        String remark = checkIn.getRemark();
        if(remark !=null){
            List<ElderFamilyVo> familyList = JSON.parseArray(remark, ElderFamilyVo.class);
            detailVo.setElderFamilyVoList(familyList);
        }
        // 查询入住配置信息
        CheckInConfig config = checkInConfigMapper.selectCheckInConfigById(id);
        if (config != null) {
            CheckInConfigVo configVo = new CheckInConfigVo();
            // 复制基础属性
            configVo.setStartDate(checkIn.getStartDate());
            configVo.setEndDate(checkIn.getEndDate());
            BeanUtils.copyProperties(config, configVo);
            detailVo.setCheckInConfigVo(configVo);
        }
        // 查询合同信息
        Contract contract = contractMapper.selectContractById(id);
        if (contract != null) {
            //添加到详情对象中
            detailVo.setContract(contract);
        }

        return detailVo;
    }

    /**
     * 新增入住配置信息
     * @param dto
     * @param checkIn
     */
    private void addCheckInConfig(CheckInApplyDto dto, CheckIn checkIn) {
        CheckInConfig checkInConfig = BeanUtil.toBean(dto.getCheckInConfigDto(), CheckInConfig.class);
        checkInConfig.setCheckInId(checkIn.getId());
        checkInConfigMapper.insert(checkInConfig);
        log.info("新增入住配置信息: id={}", checkInConfig.getId());
    }

    /**
     * 新增入住信息
     * @param dto
     * @param elder
     * @return
     */
    private CheckIn addCheckIn(CheckInApplyDto dto,Elder elder){
        CheckIn checkIn = BeanUtil.toBean(dto.getCheckInConfigDto(), CheckIn.class);
        checkIn.setElderId(elder.getId());
        checkIn.setElderName(elder.getName());
        checkIn.setIdCardNo(elder.getIdCardNo());
        checkIn.setBedNumber(elder.getBedNumber());
        //表示已经入住
        checkIn.setStatus(0);
        //设置紧急联系人
        checkIn.setRemark(JSON.toJSONString(dto.getElderFamilyDtoList()));
        save(checkIn);
        log.info("新增入住信息: id={}", checkIn.getId());
        return checkIn;
    }
    /**
     * 新增入住合同信息
     * @param dto
     */
    private void addContract(CheckInApplyDto dto,Elder elder,CheckIn checkIn){
        CheckInConfigDto checkInConfigDto = dto.getCheckInConfigDto();
        Contract contract = BeanUtil.toBean(dto.getCheckInContractDto(), Contract.class);
        //补充缺少的字段信息
        contract.setCheckInId(checkIn.getId());
        contract.setElderId(elder.getId());
        contract.setElderName(elder.getName());
        //设置开始时间和结束时间
        LocalDateTime startDate = dto.getCheckInConfigDto().getStartDate();
        contract.setStartDate(startDate);
        LocalDateTime endDate = dto.getCheckInConfigDto().getEndDate();
        contract.setEndDate(endDate);
        //获取当前系统时间，判断合同的结束时间是否大于当前系统时间，如果大于当前系统时间，则合同还未结束，如果小于当前系统时间，则合同已经结束
        LocalDateTime now = LocalDateTime.now();
        //如果合同结束时间在当前时间之前，则合同已经结束
        if(endDate.isBefore(now)){
            //丢个异常出来，抛业务异常
            throw new ServiceException("合同已经结束");
        }
        //判断合同开始时间，是否生效
        //如果合同开始的时间在当前系统时间之前，则合同已经生效
        if(startDate.isBefore(now)){
            //设置合同的状态为1，生效状态
            contract.setStatus(1);
        }else{
            //开始的时间大于当前的系统时间，则合同还未生效
            contract.setStatus(0);
        }
        //使用工具类生成一个唯一的合同编号,使用CodeGenerator工具类生成一个合同编号
        contract.setContractNumber(CodeGenerator.generateContractNumber());
        //contract对象已经构建好了，使用Mapper层的方法将contract对象插入数据库
        contractMapper.insert(contract);
        log.info("新增入住合同信息: id={}", contract.getId());
    }
    /**
     * 新增或者更新老头的信息
     * @param checkerInElderDto
     * @param bedId
     * @Param elderInDb
     */
    private Elder addOrUpdateElder(CheckInElderDto checkerInElderDto, Long bedId, Elder elderInDb) {
        //构建老人的pojo对象
        Elder elder = BeanUtil.toBean(checkerInElderDto, Elder.class);
        elder.setStatus(1);//启用状态
        elder.setBedId(bedId);
        //床位编号
        elder.setBedNumber(bedMapper.selectBedById(bedId).getBedNumber());
        if(elderInDb == null){
            //数据库中没有该老人的信息，则新增老人
            elderMapper.insert(elder);
            log.info("新增老人信息成功: id={}", elder.getId());
        }else{
            //数据库中存在该老人信息，则更新老人的信息
            //设置老人的id，从数据库中直接获取
            elder.setId(elderInDb.getId());
            //更新老人的信息
            elderMapper.updateById(elder);
            log.info("更新老人信息成功: id={}", elder.getId());
        }
        return elder;
    }
}
